package com.gimi.cloud.bbp.client.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.gimi.cloud.bbp.client.service.UserService;
import com.gimi.cloud.bbp.common.constant.RedisKeyConstant;
import com.gimi.cloud.bbp.common.enums.ResponseCodeEnum;
import com.gimi.cloud.bbp.common.exception.MsgException;
import com.gimi.cloud.bbp.common.jwt.Jwt;
import com.gimi.cloud.bbp.common.utils.JsonUtil;
import com.gimi.cloud.bbp.common.utils.StringUtil;
import com.gimi.cloud.bbp.commonService.common.CommonCoreNoticeService;
import com.gimi.cloud.bbp.commonService.redis.RedisService;
import com.gimi.cloud.bbp.dao.dao.User.UserDao;
import com.gimi.cloud.bbp.dao.dao.core.MessageDao;
import com.gimi.cloud.bbp.dao.dao.core.MessageTemplateDao;
import com.gimi.cloud.bbp.entity.core.Message;
import com.gimi.cloud.bbp.entity.core.MessageTemplate;
import com.gimi.cloud.bbp.entity.user.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Create by xiankejin on 2017-10-13
 */
@Service
public class UserServiceImpl implements UserService {

    private final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    private final UserDao userDao;
    private final CommonCoreNoticeService coreNoticeService;
    private final RedisService redisService;
    private final MessageTemplateDao messageTemplateDao;
    private final MessageDao messageDao;

    @Autowired
    public UserServiceImpl(UserDao userDao, CommonCoreNoticeService coreNoticeService,
                           RedisService redisService, MessageTemplateDao messageTemplateDao, MessageDao messageDao) {
        this.userDao = userDao;
        this.coreNoticeService = coreNoticeService;
        this.redisService = redisService;
        this.messageTemplateDao = messageTemplateDao;
        this.messageDao = messageDao;
    }


    @Override
    public User getUserByMobilePhone(User user) {
        Example example = new Example(User.class);
        example.createCriteria().andCondition("mobile_phone=", user.getMobilePhone());
        if(userDao.selectByExample(example)!=null && userDao.selectByExample(example).size()>0) {
            return userDao.selectByExample(example).get(0);
        }
        return null;
    }

    @Override
    public User getUserByUserName(String userName) {
        Example example = new Example(User.class);
        example.createCriteria().andCondition("user_name=", userName);
        if(userDao.selectByExample(example)!=null && userDao.selectByExample(example).size()>0) {
            return userDao.selectByExample(example).get(0);
        }
        return null;
    }

    @Override
    public User checkPhoneAvailable(String phone) {
        return userDao.checkPhoneAvailable(phone);
    }

    @Override
    public int countByUserName(String userName) {
        return 0;
    }

    @Override
    public User getUserByEmail(String email) {
        return userDao.getUserByEmail(email);
    }

    @Override
    public User getUserById(Integer userId) {
        User user = userDao.selectByPrimaryKey(userId);
        return user;
    }

    @Override
    public void sendCode(String phone, String createCode,String typeNid)throws MsgException {
        try {
            // 获取 注册验证码 短信模版内容
            // 注册验证码模版
            // String typeNid = SmsPortal.LOGIN_BY_PWDCODE;
            // 获取 注册验证码 短信模版内容
            List<MessageTemplate> messageTemplateList = messageTemplateDao.findByNid(typeNid);
            if(messageTemplateList!=null && messageTemplateList.size()>0){
                Map<String, Object> sendData = new HashMap<>();
                sendData.put("code", createCode);
                sendData.put("phone", phone);
                //短信模板内容
                MessageTemplate messageTemplate = messageTemplateList.get(0);
                String tpl_code = messageTemplate.getTplCode();
                //存入消息表中
                Message message = new Message();
                message.setMobile(phone);
                message.setTplId(messageTemplate.getTplId());
                message.setMsgContent(StringUtil.fillTemplet(messageTemplate.getTplContent(),sendData));
                message.setAddTime(new Date());
                // 发送短信方法
                Boolean sendMessage = coreNoticeService.sendMessage(message,1,createCode,tpl_code);
                if (!sendMessage) {
                	throw new MsgException(ResponseCodeEnum.ERR_SENT_MSG_FAIL, "短信发送失败");
				}
                long nowTime =System.currentTimeMillis();
                //验证码放入redis中
                insertResetPwdCodeToRedis(phone, createCode,typeNid);
                logger.info("code:>>>>"+createCode+"addtime:"+ nowTime);
            }
        } catch (Exception e) {
            throw new MsgException(ResponseCodeEnum.ERR_SENT_MSG_FAIL, "短信发送失败");
        }
    }



	@Override
	public User getUserBycardId(String id) {
		return userDao.getUserBycardId(id);
	}

    @Override
    public User modifyPwd(User user) {
        return userDao.modifyPwd(user.getPwd(),user.getUserId()+"");
    }

    @Override
    public void modifyPhone(String userId, String phone, int status) throws Exception {
        userDao.modifyUsername(phone,userId);
        userDao.modifyPhone(phone,userId);
//        userIdentifyService.modifyMobilePhoneStatus(userId, status, 0);
    }

    @Override
    public Boolean fixedTimeSendCode(Map pool, String phoneOrEmail) {
        if (pool.containsKey(phoneOrEmail)) {
            Map varPool = (Map) pool.get(phoneOrEmail);
            if (varPool != null) {
                long addtime = (Long) varPool.get("addtime");
                if (System.currentTimeMillis() - addtime < 60000L) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public Boolean redisFixedTimeSendCode(String phone) {
        try {
            String key = RedisKeyConstant.APP_PREFIX + "verification_code:register:" + phone;
//            String key = RedisKeyEnum.BBP_APP_PRE.getKey()+"verification_code:register:" + phone;
            String redisValue = redisService.get(key);
            if(!StringUtil.isBlank(redisValue)){
                Map<String,String> data = JsonUtil.jsonToMap(redisValue);
                String addTimeStr = data.get("addTime");
                if(!StringUtil.isBlank(addTimeStr)){
                    Long addTime = Long.parseLong(addTimeStr);
                    if (addTime != null && (System.currentTimeMillis() - addTime < 60000L)) {
                        return true;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public void insert(User user) {
         userDao.insert(user);
    }

    @Override
    public int insertReturnUserId(User isUser) {
        return userDao.insertReturnUserId(isUser);
    }

    @Override
    public void sendInitPasswordCode(String mobilePhone, String createCode) {
        try {
            // 获取 注册验证码 短信模版内容
            Map<String, Object> sendData = new HashMap<>();
            sendData.put("code", createCode);
            sendData.put("phone", mobilePhone);
            // 发送短信方法
//            coreNoticeService.sendNotice(notice,createCode);
            long nowTime = System.currentTimeMillis();
            /*Map<String, Object> varPool = new HashMap<>();
            varPool.put("code", createCode);
            varPool.put("addtime", nowTime);*/
            // 验证码放入redis中
            insertInitPwdCodeToRedis(mobilePhone, createCode);
            logger.info("code:>>>>"+createCode+"addtime:"+ nowTime);
        } catch (Exception e) {
            throw new MsgException(ResponseCodeEnum.ERR_SENT_MSG_FAIL, "短信发送失败");
        }
    }

    @Override
    public Boolean redisFixedTimeInitPassword(String mobilePhone) {
        try {
//            String key = RedisKeyEnum.BBP_APP_PRE.getKey()+"verification_code:initPassword:" + mobilePhone;
            String key = RedisKeyConstant.APP_PREFIX + "verification_code:initPassword:" + mobilePhone;
            String redisValue = redisService.get(key);
            if(!StringUtil.isBlank(redisValue)){
                Map<String,String> data = JsonUtil.jsonToMap(redisValue);
                String addTimeStr = data.get("addTime");
                if(!StringUtil.isBlank(addTimeStr)){
                    Long addTime = Long.parseLong(addTimeStr);
                    if (addTime != null && (System.currentTimeMillis() - addTime < 60000L)) {
                        return true;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public Boolean redisFixedTimeSendModifypasswordCode(String mobilePhone) {
        try {
            String key = RedisKeyConstant.APP_PREFIX + "verification_code:modifyPassword:" + mobilePhone;
//            String key = RedisKeyEnum.BBP_APP_PRE.getKey()+"verification_code:modifyPassword:" + mobilePhone;
            String redisValue = redisService.get(key);
            if(!StringUtil.isBlank(redisValue)){
                Map<String,String> data = JsonUtil.jsonToMap(redisValue);
                String addTimeStr = data.get("addTime");
                if(!StringUtil.isBlank(addTimeStr)){
                    Long addTime = Long.parseLong(addTimeStr);
                    if (addTime != null && (System.currentTimeMillis() - addTime < 60000L)) {
                        return true;
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }


    @Override
    public Map<String, String> initPersonType() {
        Map<String,String> typemap=new HashMap<>();
        typemap.put("配偶", "0");
        typemap.put("父母", "1");
        typemap.put("兄弟姐妹", "2");
        typemap.put("子女", "3");
        typemap.put("同事", "4");
        typemap.put("同学", "5");
        typemap.put("朋友", "6");
        return typemap;
    }



    @Override
    public Map<String, Object> fillBaseInfoToParams(User user) {

        //basic_info数据封装
        Map<String,Object> basic_info=new HashMap<>();
//        UserIdinfo userIdinfo=userIdinfoService.getuserIdinfo(user);
//        if(userIdinfo != null && StringUtil.isNotBlank(userIdinfo.getAddress())) {
//            basic_info.put("home_addr", userIdinfo.getAddress());//添加住址
//        }
//        basic_info.put("name", name);
//        basic_info.put("id_card_num", id_card_num);
//        basic_info.put("cell_phone_num", cell_phone_num);
        return basic_info;
    }


    private void insertResetPwdCodeToRedis(String phone,String createCode,String typeNid){
        Map<String,String> data = new HashMap<>();
        String key = RedisKeyConstant.APP_VALIDATE_CODE_PREFIX +typeNid+":"+phone;
//        String key = RedisKeyEnum.BBP_APP_PRE.getKey()+"verification_code:"+typeNid+":" + phone;
        data.put("phone",phone);
        data.put("code",createCode);
        data.put("addTime",String.valueOf(System.currentTimeMillis()));
        redisService.set(key,JsonUtil.toJson(data));
        redisService.expire(key,60 * 30);
    }

    private void insertInitPwdCodeToRedis(String phone,String createCode){
        Map<String,String> data = new HashMap<>();
        String key = RedisKeyConstant.APP_PREFIX + "verification_code:initPassword:" + phone;
//        String key = RedisKeyEnum.BBP_APP_PRE.getKey()+"verification_code:initPassword:" + phone;
        data.put("phone",phone);
        data.put("code",createCode);
        data.put("addTime",String.valueOf(System.currentTimeMillis()));
        redisService.set(key,JsonUtil.toJson(data));
        redisService.expire(key,60 * 30);
    }


	@Override
	public Integer baseInset(User isUser) {
		return userDao.baseInsert(isUser);
	}

    @Override
    public String createUserLoginToken(User user) {
        //如果当前用户为空，或者用户id为空，则直接返回
        if(null == user || null == user.getUserId()){
           return "";
        }
        //获取APP生成token规则
        JSONObject appUserTokenRule = redisService.getJSONObjectConfigByKey(RedisKeyConstant.CONFIG_KEY_APP_USER_TOKEN_RULE);
        if(null == appUserTokenRule){
            logger.info("用户token配置加载异常");
            throw new MsgException(ResponseCodeEnum.ERROR_SYSTEM_CONFNIG,"系统配置异常");
        }
        //用户token存放redis的key
        String userTokenRedisKey = RedisKeyConstant.APP_USER_TOKEN_PREFIX +user.getUserId();
        //当前登录用户token集合
        List<String> tokens = null;
        //非只允许单一登录
        if(!"1".equals(appUserTokenRule.getString("is_single_login"))){
            tokens = redisService.getList(userTokenRedisKey,String.class);
        }
        //为空，则初始化token
        if(null == tokens){
            tokens = new ArrayList<>();
        }
        JSONObject payload = new JSONObject();
        //// 用户id
        payload.put("userId",user.getUserId());
        // 用户手机号
        payload.put("phone", user.getMobilePhone());
        //用户token过期时长
        payload.put("ext",System.currentTimeMillis()+appUserTokenRule.getLong("validate_times"));
        String jwtTokenSecret = appUserTokenRule.getString("jwt_token_secret");
        String token = Jwt.createToken(payload, jwtTokenSecret);
        Map<String, Object> validResult = null;
        //使用HashSet，避免重复生成token
        HashSet<String> userNewTokens = new HashSet<>();
        for(String tempToken:tokens){
            validResult = Jwt.validToken(tempToken,jwtTokenSecret);
            //如果当前状态是有效的token则保留该token
            if(null != validResult && null != validResult.get("state") && "VALID".equals(validResult.get("state").toString())){
                userNewTokens.add(tempToken);
            }
        }
        tokens.clear();
        //设置当前用户的token为有效的token
        tokens.addAll(userNewTokens);
        //添加当前新生成的token至用户的token集合
        tokens.add(token);
        redisService.set(userTokenRedisKey,JsonUtil.toJson(tokens),appUserTokenRule.getLong("validate_times"), TimeUnit.MILLISECONDS);
        return token;
    }
}
